<template>
    <div>
        <svg :id="`heatmap-${uniqueId}`" :width="svgwidth" :height="svgheight"></svg>
    </div>
</template>
<script>
import { generateHeatData, parsePercentPoints } from './scripts/heatDataAlg';
import * as d3 from 'd3';

export default {
    name: 'heat-map',

    data() {
        return {
            uniqueId: this._uid,
            isMounted: false,
            heatData: [],
            colorScale: null,
            svgElement: null
        };
    },

    props: {
        // 定义 prop 的类型和默认值
        grain: {  // 色块显示粒度(rect的边长)
            type: Number,
            default: 4,
        },
        gradient: {  // 发热点在介质中随距离的衰减度
            type: Number,
            default: 0.01,
        },
        opacity: {   // 归一化温度0对应的透明度
            type: Number,
            default: 1.0,
        },
        svgwidth: {   // svg热力图宽度
            type: Number,
            default: 0,
        },
        svgheight: {  // svg热力图高度
            type: Number,
            default: 0,
        },
        points: {  // 发热点集合, 每个点的数据结构：{ x: 宽度百分比, y: 高度百分比, temp: 归一化温度值, intensity: 热源强度 },
            type: Array,
            default: () => [],
        },
        colorTable: {   // 色温表(低温在前)
            type: Array,
            default: () => ["#00FF00", "#FFFF00", "#FF0000"]
        },
        minTemp: {   // 最低温度
            type: Number,
            default: 20.0
        },
        maxTemp: {   // 最高温度
            type: Number,
            default: 100.0
        }
    },

    watch: {
        // 监听 prop 的变化
        grain(newVal, oldVal) {
            console.log(`grain changed from ${oldVal} to ${newVal}`);
            this.updateHeatmap();
        },
        gradient(newVal, oldVal) {
            console.log(`gradient changed from ${oldVal} to ${newVal}`);
            this.updateHeatmap();
        },
        opacity(newVal, oldVal) {
            console.log(`opacity changed from ${oldVal} to ${newVal}`);
            this.updateHeatmap();
        },
        svgwidth(newVal, oldVal) {
            console.log(`width changed from ${oldVal} to ${newVal}`);
            this.updateHeatmap();
        },
        svgheight(newVal, oldVal) {
            console.log(`height changed from ${oldVal} to ${newVal}`);
            this.updateHeatmap();
        },
        points(newVal, oldVal) {
            console.log(`points changed from ${oldVal} to ${newVal}`);
            this.updateHeatmap();
        },
        colorTable(newVal, oldVal) {
            console.log(`colorTable changed from ${oldVal} to ${newVal}`);
            if (Array.isArray(newVal) && newVal.every(item => typeof item === 'string') && newVal.length > 0) {
                this.updateHeatmap();
            }
        },
        minTemp(newVal, oldVal) {
            console.log(`minTemp changed from ${oldVal} to ${newVal}`);
            this.updateHeatmap();
        },
        maxTemp(newVal, oldVal) {
            console.log(`maxTemp changed from ${oldVal} to ${newVal}`);
            this.updateHeatmap();
        }
    },

    // 页面已加载完成生命周期点
    mounted() {
        this.isMounted = true;
        this.updateHeatmap();
    },

    // 方法定义
    methods: {
        prepareHeadmap() {
            // 设置热力图宽高
            this.svgElement = d3.select(`#heatmap-${this.uniqueId}`);
            this.svgElement.attr('width', this.svgwidth).attr('height', this.svgheight);

            // 创建颜色插值器
            const interpolators = this.colorTable.slice(0, -1).map((color, i) => {
                console.log(`index: ${i}, color1: ${color}; color2: ${this.colorTable[i + 1]}`)
                return d3.interpolateRgb(color, this.colorTable[i + 1]);
            });

            // 定义颜色比例尺
            this.colorScale = d3.scaleSequential(d => {
                const numColors = this.colorTable.length - 1;
                const threshold = d * numColors;
                const index = Math.floor(threshold);
                const fraction = threshold - index;

                if (index < numColors) {
                    return interpolators[index](fraction);
                } else {
                    // 如果d超过最大阈值，返回最后一个颜色
                    return this.colorTable[numColors];
                }
            }).domain([0, 1]);

            console.log(this.colorScale(0.0));
            console.log(this.colorScale(0.1));
            console.log(this.colorScale(0.2));
            console.log(this.colorScale(0.3));
            console.log(this.colorScale(0.4));
            console.log(this.colorScale(0.5));
            console.log(this.colorScale(0.6));
            console.log(this.colorScale(0.7));
            console.log(this.colorScale(0.8));
            console.log(this.colorScale(0.9));
            console.log(this.colorScale(1.0));

            // 创建热力图数据
            const pixelPoints = parsePercentPoints(this.points, this.svgwidth, this.svgheight, this.minTemp, this.maxTemp);
            this.heatData = generateHeatData(pixelPoints, 0, 0, this.svgwidth, this.svgheight, this.gradient, this.grain, this.opacity);
        },

        updateHeatmap() {
            if (!this.isMounted) {
                return;
            }
            this.prepareHeadmap();

            // 清空svg
            this.svgElement.selectAll('*').remove();

            // 创建方格表示热点
            const rects = this.svgElement.selectAll('rect')
                .data(this.heatData)
                .enter()
                .append('rect');

            // 设置矩形属性
            rects.attr('x', d => d.x - Math.floor(this.grain / 2)) // 减去一半的边长使矩形居中
                .attr('y', d => d.y - Math.floor(this.grain / 2))
                .attr('width', this.grain) // 正方形的宽度
                .attr('height', this.grain) // 正方形的高度
                .style('fill', d => this.colorScale(d.intensity))
                .style('opacity', d => d.opacity);
        }
    }
}
</script>